module ActiveBackground
  module DatabaseHandler
    def database(attempt=0, &block)
      database = ActiveBackground::Database.instance
      database.lock
      begin
        db = Thread.new do
          database.prepare
          self.instance_eval(&block)
          database.terminate
        end
        db.join
      rescue
        if attempt <=10
          database(attempt+1, &block)
        else
          raise 'Could not complete database task for job ' + key
          ACTIVE_BACKGROUND_LOGGER.warn 'Could not complete database task for job ' + key
        end
      end
      database.unlock
    end
  end
  
  class Database
    include Singleton
    
    def initialize
      require 'active_record'
      require File.dirname(__FILE__) + "/../../../../../config/boot.rb"
      ActiveRecord::Base.allow_concurrency = true
      ActiveRecord::Base.establish_connection(YAML.load(ERB.new(IO.read("#{RAILS_ROOT}/config/database.yml")).result)['development'])
      
      @locks = 0
      @maximum = 50
      @queue = 0
      @db = Mutex.new
    end
    
    def lock
      # TODO: need to be able to lock until database actions drop below certain point
      # lets put the thing into queue
      @db.synchronize do @queue += 1 end
      # wait till there are locks available
      while @maximum <= @locks
        sleep 1
        ACTIVE_BACKGROUND_LOGGER.info "Waiting for db lock.... \n Currently there are #{@locks} db actions running and #{@queue} in queue."
      end
      # some info
      ACTIVE_BACKGROUND_LOGGER.info "Currently there are #{@locks+1} db actions running and #{@queue-1} in queue."
      # increase lock and decrease queue
      @db.synchronize do 
        @queue -= 1
        @locks += 1
      end
    end
    
    def unlock
      # remove the lock
      @db.synchronize do
        @locks -= 1
      end
    end
    
    def prepare
      ActiveRecord::Base.connection
    end
    
    def terminate
      ActiveRecord::Base.connection.disconnect!
    end
  end
end